﻿// Copyright 2009 Mike Geise
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace Falcon.Core.Extensions
{
	using System;
	using System.Globalization;
	using System.Text;
	using Falcon.Core.Formatters;

	public static class StringExtension
	{
		private const double Kb = 1024;
		private const double Mb = 1024 * Kb;
		private const double Gb = 1024 * Mb;
		private const double Tb = 1024 * Gb;

		/// <summary>
		/// Determines whether the specified string has value.
		/// </summary>
		/// <param name="value">The value.</param>
		/// <returns>
		/// 	<c>true</c> if the specified string has value; otherwise, <c>false</c>.
		/// </returns>
		public static bool HasValue(this string value)
		{
			return !string.IsNullOrEmpty(value);
		}

		/// <summary>
		/// Gets the value or null.
		/// </summary>
		/// <param name="value">The value.</param>
		/// <returns></returns>
		public static string GetValueOrNull(this string value)
		{
			return value.HasValue() ? value : null;
		}

		/// <summary>
		/// Slugs the specified value.
		/// </summary>
		/// <param name="value">The value.</param>
		/// <returns></returns>
		public static string Slug(this string value)
		{
			if (value.HasValue())
			{
				var builder = new StringBuilder();
				var slug = value.Trim().ToLowerInvariant();

				foreach (var c in slug)
				{
					switch (c)
					{
						case ' ':
							builder.Append("-");
							break;
						case '&':
							builder.Append("and");
							break;
						default:

							if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') && c != '-')
							{
								builder.Append(c);
							}

							break;
					}
				}

				return builder.ToString();
			}

			return string.Empty;
		}

		/// <summary>
		/// Creates a hex out of the value.
		/// </summary>
		/// <param name="value">The value.</param>
		/// <returns></returns>
		public static string ToHex(this byte[] value)
		{
			var buffer = new StringBuilder();
			var table = "0123456789abcdef".ToCharArray();

			for (var i = 0; i < value.Length; i++)
			{
				buffer.Append(table[value[i] >> 4]);
				buffer.Append(table[value[i] & 15]);
			}

			return buffer.ToString();
		}

		/// <summary>
		/// Gets the size of a file.
		/// </summary>
		/// <param name="value">The value.</param>
		/// <returns></returns>
		public static string ParseFileSize(this long value)
		{
			return ParseFileSize(Convert.ToInt32(value));
		}

		/// <summary>
		/// Gets the size of a file.
		/// </summary>
		/// <param name="value">The value.</param>
		/// <returns></returns>
		public static string ParseFileSize(this int value)
		{
			if (value < Kb)
			{
				return "{0} Bytes".Fmt(value);
			}

			if (value < Mb)
			{
				return "{0} KB".Fmt(Math.Round(value / Kb, 2));
			}

			if (value < Gb)
			{
				return "{0} MB".Fmt(Math.Round(value / Mb, 2));
			}

			return value < Tb ? "{0} GB".Fmt(Math.Round(value / Gb, 2)) : "{0} TB".Fmt(Math.Round(value / Tb, 2));
		}

		/// <summary>
		/// Indents the specified value.
		/// </summary>
		/// <param name="value">The value.</param>
		/// <param name="count">The count.</param>
		/// <returns></returns>
		public static string Indent(this string value, int count)
		{
			var indent = string.Empty;

			for (var i = 1; i <= count; i++)
			{
				indent = string.Concat(indent, "-");
			}

			return string.Concat(indent, string.Empty.PadLeft(1), value);
		}

		/// <summary>
		/// Formats the specified value.
		/// </summary>
		/// <param name="value">The value.</param>
		/// <param name="parameters">The parameters.</param>
		/// <returns></returns>
		public static string Fmt(this string value, params object[] parameters)
		{
			return string.Format(CultureInfo.InvariantCulture, value, parameters);
		}

		/// <summary>
		/// Truncates the specified value.
		/// </summary>
		/// <param name="value">The value.</param>
		/// <param name="limit">The limit.</param>
		/// <returns></returns>
		public static string Truncate(this string value, int limit)
		{
			return (value.Length > limit) ? string.Concat(value.Substring(0, Math.Min(value.Length, limit)), "...") : value;
		}

		/// <summary>
		/// Uppercases the first letter in the string.
		/// </summary>
		/// <param name="value">The value.</param>
		/// <returns></returns>
		public static string UppercaseFirst(this string value)
		{
			if (!value.HasValue())
			{
				return string.Empty;
			}

			var character = value.ToCharArray();

			character[0] = char.ToUpper(character[0]);

			return new string(character);
		}

		/// <summary>
		/// Converts bbcode to html.
		/// </summary>
		/// <param name="value">The value.</param>
		/// <returns></returns>
		public static string BBCodeToHtml(this string value)
		{
			return BBCodeToHtml(value, true);
		}

		/// <summary>
		/// Converts bbcode to html.
		/// </summary>
		/// <param name="value">The value.</param>
		/// <param name="scrubHtml">if set to <c>true</c> [scrub HTML].</param>
		/// <returns></returns>
		public static string BBCodeToHtml(this string value, bool scrubHtml)
		{
			return value.HasValue() ? new BBCodeFormatter().Format(value, scrubHtml) : null;
		}
	}
}